package com.ktjiaoyu.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ktjiaoyu.server.mapper.MenuMapper;
import com.ktjiaoyu.server.mapper.MenuRoleMapper;
import com.ktjiaoyu.server.pojo.Admin;
import com.ktjiaoyu.server.pojo.AdminRole;
import com.ktjiaoyu.server.pojo.Menu;
import com.ktjiaoyu.server.pojo.MenuRole;
import com.ktjiaoyu.server.service.IMenuService;
import com.ktjiaoyu.server.vo.AdminRoleVo;
import com.ktjiaoyu.server.vo.RoleMenuVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jjx
 * @since 2024-07-10
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Resource
    MenuMapper menuMapper;
    @Resource
    MenuRoleMapper menuRoleMapper;
    @Resource
    RedisTemplate redisTemplate;

    @Override
    public List<Menu> getMenusByAdminId() {
        Admin admin=(Admin)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //第一次查询 查询数据库
        ValueOperations<String,Object> valueOperations
                = redisTemplate.opsForValue();
        List<Menu> list = (List<Menu>)valueOperations.get("menu_" + admin.getId());
        if(list==null){
            //查询数据库
            list=menuMapper.getMenusByAdminId(admin.getId());
            //在redis存放一份
            valueOperations.set("menu_" + admin.getId(),list);
        }
        //以后查询 查询redis
        return list;
    }

    @Override
    public List<Menu> getAllMenuList() {
        List<Menu> menus = menuMapper.selectList(null);
        List<Menu> list = getLevelMenuList(menus);
        return list;
    }

    @Override
    public RoleMenuVo getMenuRoleList(Integer roleId) {
        //执行查询
        List<MenuRole> list = menuRoleMapper.selectByRoleId(roleId);

        if(list==null || list.size()==0){//如果没有分配过权限
            return null;
        }

        List<Integer> mids=new ArrayList<>();
        for (MenuRole menuRole : list) {
            mids.add(menuRole.getMid());
        }
        RoleMenuVo roleMenuVo=
                new RoleMenuVo(roleId,mids.toArray(new Integer[mids.size()]));
        return roleMenuVo;
    }

    @Override
    public boolean saveMenu(Menu menu) {
        int rs = menuMapper.insert(menu);
        if(rs>0){
            return true;
        }
        return false;
    }

    @Override
    public boolean updateMenu(Menu menu) {
        int rs = menuMapper.updateById(menu);
        if(rs>0){
            return true;
        }
        return false;
    }

    @Override
    public boolean delMenuById(Integer id) {
        try {
            //1.删除与之关联的角色 menu_role
            menuRoleMapper.delete(new QueryWrapper<MenuRole>()
                    .eq("mid",id));
            //2.删除他的儿子权限
            menuMapper.delete(new QueryWrapper<Menu>()
                    .eq("parentId",id));
            //3.删除自己
            menuMapper.deleteById(id);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public List<Menu> getMenusWithRole() {
        return menuMapper.getMenusWithRole();
    }

    // 查询出每层菜单的子菜单列表
    private List<Menu> getLevelMenuList(List<Menu> menuList) {
        // oneLevelMenus 为一级菜单列表
        List<Menu> oneLevelMenus = menuList.stream().filter((menu) -> {
            // 过滤出当前角色下的一级权限列表，之后再调用map对这个一级权限列表进行遍历
            return menu.getParentId() != null && menu.getParentId() == 1;
        }).map((oneLevelMenu) -> { // 调用map对这个一级权限列表进行遍历
            // 遍历一级权限得到一级权限下的二级权限。
            oneLevelMenu.setChildren(getChildrens(oneLevelMenu, menuList));
            return oneLevelMenu;
        }).collect(Collectors.toList());
        return oneLevelMenus;
    }

    /**
     * 得到当前权限下的子权限集合
     * @param oneLevelMenu 权限对象(比如一级或二级)
     * @param menuList 为当前角色所拥有的所有权限集合
     * @return 返回当前权限下的子权限列表
     */
    private List<Menu> getChildrens(Menu oneLevelMenu, List<Menu> menuList) {
        List<Menu> childMenuList = menuList.stream().filter((menu) ->
                // 过滤条件是：权限集合中menu对象的pid父级ID == 当前权限对象oneLevelMenu的ID
                // 实现将当前权限对象oneLevelMenu的子权限列表过滤出来，如果onLevelMenu为一级权限，
                // 那么就可以把这个一级权限下的二级权限给过滤出来。
                menu.getParentId() == oneLevelMenu.getId()
        ).map((sonMenu) -> {
            // 调用map方法，将过滤出来的子权限查询进行遍历。
            sonMenu.setChildren(getChildrens(sonMenu, menuList));
            return sonMenu;
        }).collect(Collectors.toList());
        return childMenuList;
    }

}
